package com.jichaoyun.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jichaoyun.common.enums.MyExceptiontType;
import com.jichaoyun.common.ex.MyException;
//import com.jichaoyun.common.model.FileInfo;
//import com.jichaoyun.common.utils.FileUtil;
import com.jichaoyun.common.model.FileInfo;
import com.jichaoyun.common.utils.FileUtil;
import com.jichaoyun.model.app.vos.OperateCardsVo;
//import com.jichaoyun.model.entity.Fault;
//import com.jichaoyun.model.entity.FaultPicture;
//import com.jichaoyun.model.entity.dtos.FaultFormVo;
//import com.jichaoyun.model.entity.dtos.FaultParaVo;
//import com.jichaoyun.model.entity.dtos.FaultUploadVo;
import com.jichaoyun.common.model.PagedResult;
//import com.jichaoyun.model.entity.Fault;
import com.jichaoyun.model.entity.Fault;
//import com.jichaoyun.model.entity.FaultPicture;
import com.jichaoyun.model.entity.FaultPicture;
import com.jichaoyun.model.entity.LineInfo;
import com.jichaoyun.model.vo.FaultFormVo;
import com.jichaoyun.model.vo.FaultParaVo;
import com.jichaoyun.model.vo.FaultUploadVo;
import com.jichaoyun.sys.mapper.FaultMapper;
import com.jichaoyun.sys.mapper.FaultPictureMapper;
import com.jichaoyun.sys.mapper.LineInfoMapper;
import com.jichaoyun.sys.service.FaultService;


import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author zhen
* @description 针对表【fault】的数据库操作Service实现
* @createDate 2024-03-29 14:51:30
*/
@Service
public class FaultServiceImpl extends ServiceImpl<FaultMapper, Fault>
    implements FaultService {
    @Value("${web.upload-path}")
    private String uploadPath;


    @Autowired
    LineInfoMapper lineInfoMapper;

    @Autowired
    FaultMapper faultMapper;

    @Resource
    FaultPictureMapper faultPictureMapper;

    /**
     * 根据一些列的条件查找出结果
     * @param faultParaVo
     * @return
     */

    @Override
    public PagedResult getMenuListPage(FaultParaVo faultParaVo) {
        Page<Fault> faultPage = new Page<>(faultParaVo.getPageNo(), 10);
        LambdaQueryWrapper<Fault> wp = new LambdaQueryWrapper<>();
        if(faultParaVo.getHandle()==1){
            wp.eq(Fault::getOperate,"待处理");
        }
        if(faultParaVo.getHandle()==2){
            wp.eq(Fault::getOperate,"已处理");
        }
        if(faultParaVo.getTimeSelect()==1){
            LocalDateTime end = LocalDateTime.now();
            LocalDateTime start = end.minusDays(7);
            wp.le(Fault::getUploadTime,end).ge(Fault::getUploadTime,start);
        }
        if(faultParaVo.getTimeSelect()==2){
            LocalDateTime end = LocalDateTime.now();
            LocalDateTime start = end.minusMonths(1);
            wp.le(Fault::getUploadTime,end).ge(Fault::getUploadTime,start);
        }
        if(faultParaVo.getTimeSelect()==3){
            LocalDateTime end = LocalDateTime.now();
            LocalDateTime start = end.minusYears(1);
            wp.le(Fault::getUploadTime,end).ge(Fault::getUploadTime,start);
        }
        if(faultParaVo.getTimeSelect()==4){
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime start = LocalDateTime.parse(faultParaVo.getTimeStart(), dateTimeFormatter);
            LocalDateTime end = LocalDateTime.parse(faultParaVo.getTimeEnd(), dateTimeFormatter);
            wp.le(Fault::getUploadTime,end).ge(Fault::getUploadTime,start);
        }
        if(faultParaVo.getLine()!=-1){
            try {
                String lineName = lineInfoMapper.selectById(faultParaVo.getLine()).getLineAlias();
                if(lineName==null || lineName.equals("")){
                    lineName = lineInfoMapper.selectById(faultParaVo.getLine()).getLineName();
                }
                wp.eq(Fault::getLineName,lineName);
            }
            catch (NullPointerException e){
                throw new MyException(MyExceptiontType.NULL1,null);
            }
        }

        if (faultParaVo.getType()==1){
            wp.eq(Fault::getType,"管线故障");
        }
        if (faultParaVo.getType()==2){
            wp.eq(Fault::getType,"线路破损");
        }
        if (faultParaVo.getType()==3){
            wp.eq(Fault::getType,"其他故障");
        }
        wp.orderByDesc(Fault::getUploadTime);
        faultMapper.selectPage(faultPage,wp);
        PagedResult pagedResult = new PagedResult();

        List<Fault> records = faultPage.getRecords();
        //更新pic名称列表
        for (Fault record : records) {
            List<String> picNameList = new ArrayList<>();
            LambdaQueryWrapper<FaultPicture> wp1 = new LambdaQueryWrapper<>();
            wp1.eq(FaultPicture::getNum,record.getNum()).eq(FaultPicture::getType, "故障");
            List<FaultPicture> faultPictures = faultPictureMapper.selectList(wp1);
            for (FaultPicture faultPicture : faultPictures) {
                picNameList.add(faultPicture.getPicName());
            }
            record.setPicNameList(picNameList);
        }

        pagedResult.setRows(records);
        pagedResult.setPages(faultPage.getPages());
        pagedResult.setTotal(faultPage.getTotal());

        return pagedResult;
    }

    /**
     * 获取故障的通知
     * @return
     */
    @Override
    public List<FaultFormVo> getFaultInformList() {
        LambdaQueryWrapper<Fault> wp = new LambdaQueryWrapper<>();
        wp.eq(Fault::getIsRead,false).eq(Fault::getOperate,"已处理").orderByDesc(Fault::getUploadTime);
        List<Fault> faults = faultMapper.selectList(wp);
        ArrayList<FaultFormVo> resList = new ArrayList<>();
        for (Fault fault : faults) {
            FaultFormVo faultFormVo = new FaultFormVo();
            faultFormVo.setStatus(fault.getStatus());
            faultFormVo.setType(fault.getType());
            faultFormVo.setSite(fault.getSite());

            LocalDateTime now = LocalDateTime.now();
            Duration between = Duration.between(fault.getUploadTime(),now);
            if(between.toHours()<1){
                faultFormVo.setTime(between.toMinutes()+"分钟前");
            }else if(between.toHours()<24){
                faultFormVo.setTime(between.toHours()+"小时前");
            }else{
                faultFormVo.setTime(between.toDays()+"天前");
            }
            resList.add(faultFormVo);
        }
        return resList;
    }

    /**
     * app 故障-实时概括-故障类型
     * @return
     */
    @Override
    public HashMap<String, Integer> getTodayFaultInfo() {
        HashMap<String, Integer> resMap = new HashMap<>();
        LocalDateTime start = LocalDateTime.now().with(LocalTime.MIN);
        LocalDateTime end = start.plusDays(1);
        LambdaQueryWrapper<Fault> wp = new LambdaQueryWrapper<>();
        wp.between(Fault::getUploadTime,start,end);
        List<Fault> faults = faultMapper.selectList(wp);
        int xianlu = 0;
        int guanxian = 0;
        int qita = 0;
        int chuli = 0;
        int nochuli = 0;
        int total = 0;
        for (Fault fault : faults) {
            if(fault.getType().equals("管线故障")){
                guanxian++;
            }
            if(fault.getType().equals("线路破损")){
                xianlu++;
            }
            if(fault.getType().equals("其他故障")){
                qita++;
            }
            if(fault.getStatus().equals("已处理")){
                chuli++;
            }
            if(fault.getStatus().equals("待处理")){
                nochuli++;
            }
            total++;
        }
        resMap.put("管线故障",guanxian);
        resMap.put("线路破损",xianlu);
        resMap.put("其他故障",qita);
        resMap.put("已处理",chuli);
        resMap.put("待处理",nochuli);
        resMap.put("日新增",total);
        return resMap;
    }

    @Override
    public List<Map<String, Object>> getTodayFaultDetail() {
        List<Map<String, Object>> resList = new ArrayList<>();

        LambdaQueryWrapper<LineInfo> wp1 = new LambdaQueryWrapper<>();
        wp1.orderByAsc(LineInfo::getLineNum);
        List<LineInfo> lineInfos = lineInfoMapper.selectList(wp1);

        LocalDateTime start = LocalDateTime.now().with(LocalTime.MIN);
        LocalDateTime end = start.plusDays(1);

        for (LineInfo lineInfo : lineInfos) {
            String lineName = lineInfo.getLineAlias();
            if(lineName==null || lineName.equals("")){
                lineName = lineInfo.getLineName();
            }
            LambdaQueryWrapper<Fault> wp = new LambdaQueryWrapper<>();
            wp.eq(Fault::getLineName,lineName).between(Fault::getUploadTime,start,end);
            List<Fault> faults = faultMapper.selectList(wp);
            if(faults.size()!=0){
                int ok =0;
                int no =0;
                for (Fault fault : faults) {
                    if(fault.getOperate().equals("已处理")){
                        ok++;
                    }else{
                        no++;
                    }
                }
                HashMap<String, Object> map = new HashMap<>();
                map.put("名称",lineName);
                map.put("今日新增",faults.size());
                map.put("已处理",ok);
                map.put("待处理",no);
                resList.add(map);
            }

        }
        return resList;
    }

    @Override
    public List<OperateCardsVo> getFaultOperateCards() {
        LambdaQueryWrapper<Fault> wp = new LambdaQueryWrapper<>();
        wp.eq(Fault::getOperate,"待处理");
        List<Fault> faults = faultMapper.selectList(wp);
        ArrayList<OperateCardsVo> vos = new ArrayList<>();
        for (Fault fault : faults) {
            OperateCardsVo operateCardsVo = new OperateCardsVo();
            BeanUtils.copyProperties(fault,operateCardsVo);
            vos.add(operateCardsVo);
        }
        return vos;
    }

    /**
     * app故障信息上传
     * @return
     */
    @Override
    public Integer faultUpload(FaultUploadVo faultvo) {
        Fault fault = new Fault();
        BeanUtils.copyProperties(faultvo,fault);
        fault.setIsRead(false);
        //生成num的号码编号
        LocalDateTime start = LocalDateTime.now().with(LocalTime.MIN);
        LocalDateTime end = start.plusDays(1);
        LambdaQueryWrapper<Fault> wp = new LambdaQueryWrapper<>();
        wp.between(Fault::getUploadTime,start,end);
        Long count = faultMapper.selectCount(wp);
//        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDateTime now = LocalDateTime.now();
        int year = now.getYear();
        int month = now.getMonthValue();
        int day = now.getDayOfMonth();
        Integer num = year%100*10000000+month*100000+day*1000+count.intValue();
        fault.setNum(num.toString());
        fault.setUploadTime(LocalDateTime.now());
        fault.setOperate("待处理");
        //插入故障记录
        int insert = faultMapper.insert(fault);
        LambdaQueryWrapper<Fault> delwp = new LambdaQueryWrapper<>();
        delwp.eq(Fault::getNum,num.toString());

        if (insert==1){
            return num ;
        }
        return -1;
    }

    /**
     * app故障信息上传图片
     * @return
     */
    @Override
    public boolean faultUpload(MultipartFile file, Integer num) {
        LambdaQueryWrapper<Fault> delwp = new LambdaQueryWrapper<>();
        delwp.eq(Fault::getNum,num.toString());

        FileUtil util = new FileUtil();
        FileInfo info = util.upload(file, uploadPath);
        if (info==null){
            faultMapper.delete(delwp);
            throw new MyException(MyExceptiontType.IMAGEUPLOADFAILD2,null);
        }
        if(file.getSize() > 20*1024*1024){
            util.deleteFile(info.getSavePath());
            faultMapper.delete(delwp);
            throw new MyException(MyExceptiontType.IMAGEUPLOADFAILD1,null);
        }else if(!(info.getSuffix().equals(".jpg")||info.getSuffix().equals(".png")
                ||info.getSuffix().equals(".JPG")||info.getSuffix().equals(".PNG")
                ||info.getSuffix().equals(".jpeg")||info.getSuffix().equals(".JPEG"))){
            util.deleteFile(info.getSavePath());
            faultMapper.delete(delwp);
            throw new MyException(MyExceptiontType.IMAGEUPLOADFAILD3,null);
        }else{
            FaultPicture faultPicture = new FaultPicture();
            faultPicture.setNum(num.toString());
            faultPicture.setPicName(info.getFileName());
            faultPicture.setType("故障");
            faultPictureMapper.insert(faultPicture);
        }
        return true ;
    }

    /**
     * 故障处理部分的回显
     * @return
     */
    @Override
    public Fault getFaultOperateVo(Integer id) {
        Fault fault = faultMapper.selectById(id);
        return fault;
    }

    /**
     * 故障处理
     * @param files
     * @param operateInfo
     * @return
     */
    @Override
    public Boolean faultOperate(List<MultipartFile> files, String operateInfo,String operatePeople,Integer id) {
        //先处理保存图片
        Fault fault = faultMapper.selectById(id);
        for (MultipartFile file : files) {
            FileUtil util = new FileUtil();
            FileInfo info = util.upload(file, uploadPath);
            if (info==null){
                throw new MyException(MyExceptiontType.IMAGEUPLOADFAILD2,null);
            }
            if(file.getSize() > 20*1024*1024){
                util.deleteFile(info.getSavePath());
                throw new MyException(MyExceptiontType.IMAGEUPLOADFAILD1,null);
            }else if(!(info.getSuffix().equals(".jpg")||info.getSuffix().equals(".png")
                    ||info.getSuffix().equals(".JPG")||info.getSuffix().equals(".PNG")
                    ||info.getSuffix().equals(".jpeg")||info.getSuffix().equals(".JPEG"))){
                util.deleteFile(info.getSavePath());
                throw new MyException(MyExceptiontType.IMAGEUPLOADFAILD3,null);
            }else{
                FaultPicture faultPicture = new FaultPicture();
                faultPicture.setNum(fault.getNum());
                faultPicture.setPicName(info.getFileName());
                faultPicture.setType("处理");
                faultPictureMapper.insert(faultPicture);
            }
        }
        fault.setOperateTime(LocalDateTime.now());
        fault.setOperateInfo(operateInfo);
        fault.setOperatePeople(operatePeople);
        fault.setOperate("已处理");
        faultMapper.updateById(fault);

        return true;
    }

    /**
     * 获取故障的排行
     * @return
     */
    @Override
    public List<Map<String, Object>> getFaultRank() {
        ArrayList<Map<String,Object>> res = new ArrayList<>();

        //查找该路线的别名
//        LambdaQueryWrapper<LineInfo> lineWp = new LambdaQueryWrapper<>();
//        LineInfo lineInfo = lineInfoMapper.selectById(lineId);
//        String lineName = lineInfo.getLineAlias()==null||lineInfo.getLineAlias().equals("") ? lineInfo.getLineName():lineInfo.getLineAlias();

        LocalDateTime start = LocalDateTime.now().with(LocalTime.MIN);
        LocalDateTime end = start.plusDays(1);
        LocalDateTime start1 = LocalDateTime.now().with(LocalTime.MIN).minusDays(1);
        LocalDateTime end1 = start1.plusDays(1);
        QueryWrapper<Fault> wp = new QueryWrapper<>();
        wp.select("line_name","count(*) as count")
                .between("upload_time",start,end)
                .groupBy("line_name");
        List<Map<String, Object>> list = faultMapper.selectMaps(wp);
        for (Map<String, Object> map : list) {
            String line_name = (String) map.get("line_name");
            LambdaQueryWrapper<Fault> wp1 = new LambdaQueryWrapper<>();
            wp1.eq(Fault::getLineName,line_name);
            wp1.between(Fault::getUploadTime,start1,end1);
            Long aLong = faultMapper.selectCount(wp1);
            int add =  (int) map.get("count") - aLong.intValue();
            map.put("add",add);
        }
        list.sort((o1, o2) -> ((Integer) o2.get("count")).compareTo((Integer) o1.get("count")));

        //计算总的故障数量
        int total=0;
        if (list.size()!=0){
            for (Map<String, Object> map : list) {
                total+=(int)map.get("count");
            }
        }
        HashMap<String, Object> totalMap = new HashMap<>();
        totalMap.put("故障概况-故障频次",total);
        list.add(totalMap);

        HashMap<String, Object> faultRateMap = new HashMap<>();
        LambdaQueryWrapper<LineInfo> wpline = new LambdaQueryWrapper<>();
//        wpline.orderByAsc(LineInfo::getLineNum);
        Float rate = (list.size()-1)*1f/ lineInfoMapper.selectCount(wpline).intValue();
        faultRateMap.put("故障率",rate);
        list.add(faultRateMap);
        return list;
    }

    @Override
    public PagedResult getAppFaultList(FaultParaVo faultParaVo) {
//        Page<Fault> faultPage = new Page<>(faultParaVo.getPageNo(), 10);
        LambdaQueryWrapper<Fault> wp = new LambdaQueryWrapper<>();
        if(faultParaVo.getHandle()==1){
            wp.eq(Fault::getOperate,"待处理");
        }
        if(faultParaVo.getHandle()==2){
            wp.eq(Fault::getOperate,"已处理");
        }
        if(faultParaVo.getTimeSelect()==1){
            LocalDateTime end = LocalDateTime.now();
            LocalDateTime start = end.minusDays(7);
            wp.le(Fault::getUploadTime,end).ge(Fault::getUploadTime,start);
        }
        if(faultParaVo.getTimeSelect()==2){
            LocalDateTime end = LocalDateTime.now();
            LocalDateTime start = end.minusMonths(1);
            wp.le(Fault::getUploadTime,end).ge(Fault::getUploadTime,start);
        }
        if(faultParaVo.getTimeSelect()==3){
            LocalDateTime end = LocalDateTime.now();
            LocalDateTime start = end.minusYears(1);
            wp.le(Fault::getUploadTime,end).ge(Fault::getUploadTime,start);
        }
        if(faultParaVo.getTimeSelect()==4){
            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            LocalDateTime start = LocalDateTime.parse(faultParaVo.getTimeStart(), dateTimeFormatter);
            LocalDateTime end = LocalDateTime.parse(faultParaVo.getTimeEnd(), dateTimeFormatter);
            wp.le(Fault::getUploadTime,end).ge(Fault::getUploadTime,start);
        }
        if(faultParaVo.getLine()!=-1){
            try {
                String lineName = lineInfoMapper.selectById(faultParaVo.getLine()).getLineAlias();
                if(lineName==null || lineName.equals("")){
                    lineName = lineInfoMapper.selectById(faultParaVo.getLine()).getLineName();
                }
                wp.eq(Fault::getLineName,lineName);
            }
            catch (NullPointerException e){
                throw new MyException(MyExceptiontType.NULL1,null);
            }
        }

        if (faultParaVo.getType()==1){
            wp.eq(Fault::getType,"管线故障");
        }
        if (faultParaVo.getType()==2){
            wp.eq(Fault::getType,"线路破损");
        }
        if (faultParaVo.getType()==3){
            wp.eq(Fault::getType,"其他故障");
        }
        wp.orderByDesc(Fault::getId);
        List<Fault> faults = faultMapper.selectList(wp);
        PagedResult pagedResult = new PagedResult();

        //查询故障以及处理的图片名称列表
        List<Fault> records = faults;
        for (Fault record : records) {
            //故障图片
            List<String> picNameList = new ArrayList<>();
            LambdaQueryWrapper<FaultPicture> wp1 = new LambdaQueryWrapper<>();
            wp1.eq(FaultPicture::getNum,record.getNum()).eq(FaultPicture::getType, "故障");
            List<FaultPicture> faultPictures = faultPictureMapper.selectList(wp1);
            for (FaultPicture faultPicture : faultPictures) {
                picNameList.add(faultPicture.getPicName());
            }
            record.setPicNameList(picNameList);
            //处理图片
            List<String> operatePicNameList = new ArrayList<>();
            LambdaQueryWrapper<FaultPicture> wp2 = new LambdaQueryWrapper<>();
            wp2.eq(FaultPicture::getNum,record.getNum()).eq(FaultPicture::getType,"处理");
            List<FaultPicture> optlist = faultPictureMapper.selectList(wp2);
            for (FaultPicture faultPicture : optlist) {
                operatePicNameList.add(faultPicture.getPicName());
            }
            record.setOperatePicNameList(operatePicNameList);
        }
        pagedResult.setRows(records);

        return pagedResult;
    }

}




